package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.PermissionUtils;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.elm.dto.CommentCreateDTO;
import cn.edu.tju.elm.dto.CommentResponseDTO;
import cn.edu.tju.elm.dto.CommentUpdateDTO;
import cn.edu.tju.elm.mapper.CommentMapper;
import cn.edu.tju.elm.model.Comment;
import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.service.CommentService;
import cn.edu.tju.elm.service.OrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * ClassName: CommentController
 * Package: cn.edu.tju.elm.controller
 * Description: 评论管理控制器
 *
 * @Author System Generated
 * @Create 2025/10/30
 * @Version 1.0
 */
@RestController
@RequestMapping("/api/comments")
@Tag(name = "管理评论", description = "对评论进行增删改查和评分管理")
public class CommentController {

    @Autowired
    private UserService userService;

    @Autowired
    private CommentService commentService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private PermissionUtils permissionUtils;

    // 公共访问接口 - 无需认证
    @GetMapping("/public/business/{businessId}")
    @Operation(summary = "查询店铺的所有评论（公共访问）", description = "无需登录即可查看店铺评论")
    public HttpResult<List<CommentResponseDTO>> getBusinessCommentsPublic(@PathVariable Long businessId) {
        try {
            List<Comment> comments = commentService.getCommentsByBusinessId(businessId);
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询店铺评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/public/business/{businessId}/statistics")
    @Operation(summary = "查询店铺评论统计（公共访问）", description = "无需登录即可查看店铺评分统计")
    public HttpResult<Map<String, Object>> getBusinessStatisticsPublic(@PathVariable Long businessId) {
        try {
            Map<String, Object> statistics = commentService.getBusinessCommentStatistics(businessId);
            return HttpResult.success(statistics);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论统计失败: " + e.getMessage());
        }
    }

    @GetMapping("/public/business/{businessId}/rating/{rating}")
    @Operation(summary = "根据评分查询店铺评论（公共访问）", description = "查询特定评分的评论")
    public HttpResult<List<CommentResponseDTO>> getBusinessCommentsByRatingPublic(@PathVariable Long businessId,
                                                                                   @PathVariable Integer rating) {
        try {
            if (rating < 1 || rating > 5) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "评分必须在1-5之间");
            }
            List<Comment> comments = commentService.getCommentsByBusinessIdAndRating(businessId, rating);
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    // 需要认证的接口
    @PostMapping("")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "添加评论", description = "用户对已完成的订单进行评论和评分")
    public HttpResult<CommentResponseDTO> addComment(@Valid @RequestBody CommentCreateDTO commentCreateDTO) {
        try {
            User user = userService.getUserWithAuthorities().get();
            
            // 检查订单是否存在
            Optional<Order> orderOpt = orderService.getOrderById(commentCreateDTO.getOrderId());
            if (orderOpt.isEmpty()) {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "订单不存在");
            }
            
            Order order = orderOpt.get();
            
            // 检查订单是否属于当前用户
            if (!permissionUtils.isAdmin() && !order.getCustomer().getId().equals(user.getId())) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权评论该订单");
            }
            
            // 检查订单是否已评论
            if (commentService.hasCommented(commentCreateDTO.getOrderId())) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "该订单已评论");
            }
            
            Comment comment = commentMapper.createDtoToComment(commentCreateDTO);
            comment.setCustomer(user);
            comment.setBusiness(order.getBusiness());
            LocalDateTime now = LocalDateTime.now();
            comment.setCreator(user.getId());
            comment.setCreateTime(now);
            comment.setUpdater(user.getId());
            comment.setUpdateTime(now);
            comment.setDeleted(false);
            
            Comment savedComment = commentService.addComment(comment);
            CommentResponseDTO responseDTO = commentMapper.commentToResponseDTO(savedComment);
            return HttpResult.success(responseDTO);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "添加评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER','BUSINESS')")
    @Operation(summary = "根据ID查询评论")
    public HttpResult<CommentResponseDTO> getCommentById(@PathVariable Long id) {
        try {
            Optional<Comment> comment = commentService.getCommentById(id);
            if (comment.isPresent()) {
                CommentResponseDTO responseDTO = commentMapper.commentToResponseDTO(comment.get());
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "评论不存在");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/order/{orderId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER','BUSINESS')")
    @Operation(summary = "根据订单ID查询评论")
    public HttpResult<CommentResponseDTO> getCommentByOrderId(@PathVariable Long orderId) {
        try {
            Optional<Comment> comment = commentService.getCommentByOrderId(orderId);
            if (comment.isPresent()) {
                CommentResponseDTO responseDTO = commentMapper.commentToResponseDTO(comment.get());
                return HttpResult.success(responseDTO);
            } else {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "该订单暂无评论");
            }
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/current-user")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "查询当前用户的所有评论")
    public HttpResult<List<CommentResponseDTO>> getCurrentUserComments() {
        try {
            User user = userService.getUserWithAuthorities().get();
            List<Comment> comments = commentService.getCommentsByCustomerId(user.getId());
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/business/{businessId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS','USER')")
    @Operation(summary = "查询店铺的所有评论")
    public HttpResult<List<CommentResponseDTO>> getBusinessComments(@PathVariable Long businessId) {
        try {
            List<Comment> comments = commentService.getCommentsByBusinessId(businessId);
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询店铺评论失败: " + e.getMessage());
        }
    }

    @GetMapping("/business/{businessId}/statistics")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS')")
    @Operation(summary = "查询店铺评论统计信息", description = "包含平均评分、评分分布、好评率等")
    public HttpResult<Map<String, Object>> getBusinessStatistics(@PathVariable Long businessId) {
        try {
            Map<String, Object> statistics = commentService.getBusinessCommentStatistics(businessId);
            return HttpResult.success(statistics);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论统计失败: " + e.getMessage());
        }
    }

    @GetMapping("/rating/{rating}")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS','USER')")
    @Operation(summary = "根据评分查询评论")
    public HttpResult<List<CommentResponseDTO>> getCommentsByRating(@PathVariable Integer rating) {
        try {
            if (rating < 1 || rating > 5) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "评分必须在1-5之间");
            }
            List<Comment> comments = commentService.getCommentsByRating(rating);
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    @GetMapping("")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "查询所有评论", description = "仅管理员可访问")
    public HttpResult<List<CommentResponseDTO>> getAllComments() {
        try {
            List<Comment> comments = commentService.getAllComments();
            List<CommentResponseDTO> responseDTOs = commentMapper.commentsToResponseDTOs(comments);
            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询评论失败: " + e.getMessage());
        }
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessOrderData(@commentService.getCommentById(#id).get().getCustomer().getId())")
    @Operation(summary = "修改评论", description = "用户只能修改自己的评论")
    public HttpResult<CommentResponseDTO> updateComment(@PathVariable Long id,
                                                         @Valid @RequestBody CommentUpdateDTO commentUpdateDTO) {
        try {
            User user = userService.getUserWithAuthorities().get();
            Optional<Comment> existingComment = commentService.getCommentById(id);
            
            if (existingComment.isEmpty()) {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "评论不存在");
            }
            
            Comment comment = existingComment.get();
            
            // 只有管理员可以修改reply字段
            if (commentUpdateDTO.getReply() != null && !permissionUtils.isAdmin() && !permissionUtils.isBusiness()) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权限添加商家回复");
            }
            
            // 如果是商家，检查是否是自己店铺的评论
            if (permissionUtils.isBusiness() && !permissionUtils.isAdmin()) {
                if (!comment.getBusiness().getBusinessOwner().getId().equals(user.getId())) {
                    return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权限回复该评论");
                }
            }
            
            // 更新字段
            if (commentUpdateDTO.getRating() != null) {
                comment.setRating(commentUpdateDTO.getRating());
            }
            if (commentUpdateDTO.getContent() != null) {
                comment.setContent(commentUpdateDTO.getContent());
            }
            if (commentUpdateDTO.getReply() != null) {
                comment.setReply(commentUpdateDTO.getReply());
            }
            if (commentUpdateDTO.getDeleted() != null) {
                comment.setDeleted(commentUpdateDTO.getDeleted());
            }
            
            comment.setUpdater(user.getId());
            comment.setUpdateTime(LocalDateTime.now());
            
            Comment updatedComment = commentService.updateComment(comment);
            CommentResponseDTO responseDTO = commentMapper.commentToResponseDTO(updatedComment);
            return HttpResult.success(responseDTO);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "修改评论失败: " + e.getMessage());
        }
    }

    @PatchMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessOrderData(@commentService.getCommentById(#id).get().getCustomer().getId())")
    @Operation(summary = "部分修改评论")
    public HttpResult<CommentResponseDTO> partiallyUpdateComment(@PathVariable Long id,
                                                                  @RequestBody CommentUpdateDTO commentUpdateDTO) {
        return updateComment(id, commentUpdateDTO);
    }

    @PatchMapping("/{id}/reply")
    @PreAuthorize("hasAuthority('ADMIN') or (hasAuthority('BUSINESS') and @permissionUtils.canAccessBusinessData(@commentService.getCommentById(#id).get().getBusiness().getBusinessOwner().getId()))")
    @Operation(summary = "商家回复评论", description = "商家可以回复自己店铺的评论")
    public HttpResult<CommentResponseDTO> replyComment(@PathVariable Long id,
                                                        @RequestParam String reply) {
        try {
            User user = userService.getUserWithAuthorities().get();
            Optional<Comment> existingComment = commentService.getCommentById(id);
            
            if (existingComment.isEmpty()) {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "评论不存在");
            }
            
            Comment comment = existingComment.get();
            comment.setReply(reply);
            comment.setUpdater(user.getId());
            comment.setUpdateTime(LocalDateTime.now());
            
            Comment updatedComment = commentService.updateComment(comment);
            CommentResponseDTO responseDTO = commentMapper.commentToResponseDTO(updatedComment);
            return HttpResult.success(responseDTO);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "回复评论失败: " + e.getMessage());
        }
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessOrderData(@commentService.getCommentById(#id).get().getCustomer().getId())")
    @Operation(summary = "删除评论", description = "用户可以删除自己的评论，管理员可以删除任何评论")
    public HttpResult<String> deleteComment(@PathVariable Long id) {
        try {
            Optional<Comment> existingComment = commentService.getCommentById(id);
            if (existingComment.isEmpty()) {
                return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "评论不存在");
            }
            
            commentService.deleteComment(id);
            return HttpResult.success("删除成功");
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除评论失败: " + e.getMessage());
        }
    }
}



